package com.ts.camera2.Camera2Oes

import android.content.Context
import android.graphics.SurfaceTexture
import android.opengl.EGL14
import android.opengl.GLES11Ext
import android.opengl.GLES20
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.os.Environment
import android.util.Log
import com.ts.audiocamera.R
import com.ts.camera2.camera.Camera2Wrapper
import com.ts.mediacodec.MediaRecorder
import com.ts.opengl.simpleDraw.openglUtil
import java.io.File
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class CameraOSERender(var context:Context,var glSurfaceView:GLSurfaceView?):GLSurfaceView.Renderer {
    var mCamera2: Camera2Wrapper?=null


    val vertices= floatArrayOf(
        // 坐标            纹理
        // X,Y,Z   ,U,V
        -1.0f, -1.0f, 0f, 0f, 0f,
        1.0f, -1.0f, 0f, 1f, 0f,
        -1.0f, 1.0f, 0f, 0f, 1f,
        1.0f, 1.0f, 0f, 1f, 1f,
    )

    var mMediaRecorder: MediaRecorder?=null

//    val TEXTURE_ROTATED_180: FloatArray = floatArrayOf(
//        -1.0f,  -1.0f, 0.0f,  0f, 0f,
//        1.0f, -1.0f, 0.0f,   1f, 0f,
//        -1.0f, 1.0f, 0.0f,   0f, 1f,
//        1.0f,  1.0f, 0.0f,   1f, 1f,
//    )

//    val elementfbo by lazy {
//        openglUtil.createFloatBuffer(TEXTURE_ROTATED_180)
//    }

    val indexidfbo by lazy {
        openglUtil.createIntBuffer(index)
    }

    val index= intArrayOf(
        0,1,2,
        1,2,3
    )

    val element by lazy {
        openglUtil.createFloatBuffer(vertices)
    }

    val indexid by lazy {
        openglUtil.createIntBuffer(index)
    }

    var program=0;

   var fboprogram=0;

    var surfaceTexture:SurfaceTexture?=null

    var vbo=IntArray(1)
    var vao=IntArray(1)
    var ebo=IntArray(1)


    fun startRecorder(){
        mMediaRecorder?.start()

    }


    private  val TAG = "CameraOSERender"

    var uTextureMatrix=0;
    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        mCamera2=Camera2Wrapper(context)
        fboprogram=openglUtil.createProgram(context, R.raw.camera_oes_vert,R.raw.camera_oes_frag)

        program=openglUtil.createProgram(context, R.raw.camera_oes_fbo_vert,R.raw.camera_oes_fbo_frag)
        uTextureMatrix=GLES30.glGetUniformLocation(fboprogram,"uTextureMatrix")
        createOESTexture()

//        surfaceTexture?.attachToGLContext(texture[0])
//        SurfaceTexture
        GLES30.glGenBuffers(vbo.size,vbo,0)//GLES30.GL_ARRAY_BUFFER,)
        GLES30.glGenVertexArrays(vao.size,vao,0)
        GLES30.glBindVertexArray(vao[0])
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,vbo[0])
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,element.capacity()*4,element,GLES30.GL_STATIC_DRAW)

        element.position(0)

        GLES30.glVertexAttribPointer(0,3,GLES30.GL_FLOAT,false,5*4,0)
        GLES30.glEnableVertexAttribArray(0)

        element.position(3)
        GLES30.glVertexAttribPointer(1,2,GLES30.GL_FLOAT,false,5*4,3*4)
        GLES30.glEnableVertexAttribArray(1)

        GLES30.glGenBuffers(ebo.size,ebo,0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,ebo[0])

        GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,indexid.capacity()*4,indexid,GLES30.GL_STATIC_DRAW)

        GLES30.glBindVertexArray(0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,0)




//        GLES30.glGenBuffers(vbofbo.size,vbofbo,0)//GLES30.GL_ARRAY_BUFFER,)
//        GLES30.glGenVertexArrays(vaofbo.size,vaofbo,0)
//        GLES30.glBindVertexArray(vaofbo[0])
//        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,vbofbo[0])
//        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,elementfbo.capacity()*4,elementfbo,GLES30.GL_STATIC_DRAW)

//        elementfbo.position(0)

//        GLES30.glVertexAttribPointer(0,3,GLES30.GL_FLOAT,false,5*4,0)
//        GLES30.glEnableVertexAttribArray(0)

//        elementfbo.position(3)
//        GLES30.glVertexAttribPointer(1,2,GLES30.GL_FLOAT,false,5*4,3*4)
//        GLES30.glEnableVertexAttribArray(1)

//        GLES30.glGenBuffers(ebofbo.size,ebofbo,0)//GLES30.GL_ARRAY_BUFFER,)
//        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,ebofbo[0])

//        GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,indexidfbo.capacity()*4,indexidfbo,GLES30.GL_STATIC_DRAW)

//        GLES30.glBindVertexArray(0)
//        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,0)
//        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,0)

        surfaceTexture=SurfaceTexture(textureOes[0])
        surfaceTexture?.setOnFrameAvailableListener {
            glSurfaceView?.requestRender()
        }

        if (!initc){


            initc=true;
            //当前线程
            val path = File(Environment.getExternalStorageDirectory(), "input1test.mp4").absolutePath
//            checkGlError("glBindTextu222re23333232323232")
            mCamera2?.startCamera(surfaceTexture)
            mMediaRecorder=MediaRecorder(path,mCamera2?.previewSize?.width!!,mCamera2?.previewSize?.height!!,context,EGL14.eglGetCurrentContext())
        }

    }


    var textureOes=IntArray(1)
    private fun createOESTexture(){
        GLES30.glGenTextures(textureOes.size,textureOes,0)
        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,textureOes[0])
        GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
        GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,0)
    }
    private val mFBOTextures by lazy {
        IntArray(1)
    }

    private val mFrameBuffers by lazy {
        IntArray(1)
    }


    fun stopRecord() {
        mMediaRecorder!!.stop()
    }
    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0,0,width,height)
        surfaceTexture?.setDefaultBufferSize(width,height)
        loadFBO(width,height);
    }
    private fun destroyFrameBuffers() {
        GLES20.glDeleteTextures(1, mFBOTextures, 0)
        GLES20.glDeleteFramebuffers(1, mFrameBuffers, 0)
    }

    protected fun createTexture(textures: IntArray) {
        GLES20.glGenTextures(textures.size, textures, 0)
        for (texture in textures) {
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture)
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST)
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR)
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE)
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE)
            Log.e(TAG, "create texture, id 12= ${texture}")
        }

    }
    private fun loadFBO(width: Int, height: Int) {
        destroyFrameBuffers()
        //Create FrameBuffer
        GLES20.glGenFramebuffers(mFrameBuffers.size, mFrameBuffers, 0)
        //Texture in FBO
//        Log.e(TAG, "create texture, id loadFBO  = ")
        createTexture(mFBOTextures)
        //让fbo与 纹理发生关系
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFBOTextures[0])
        Log.e(TAG, "create texture, id loadFBO  = "+mFBOTextures[0])
        //Specifies the format of the output image of the FBO texture RGBA
        GLES20.glTexImage2D(
            GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height,
            0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null
        )

        //绑定纹理 和fbo
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,
            mFrameBuffers[0]
        )

        GLES20.glFramebufferTexture2D(
            GLES20.GL_FRAMEBUFFER,
            GLES20.GL_COLOR_ATTACHMENT0,
            GLES20.GL_TEXTURE_2D,
            mFBOTextures[0], 0
        )
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0)
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0)
    }



    fun checkGlError(op: String) {
        val error = GLES20.glGetError()
        if (error != GLES20.GL_NO_ERROR) {
            val msg = op + ": glError 0x" + Integer.toHexString(error)
            Log.e(TAG, "checkGlError"+ msg)
        }
    }
    var initc=false;
    var mtx= FloatArray(16)
    override fun onDrawFrame(gl: GL10?) {

//        if (!initc){
//            initc=true;
//            mCamera2?.startCamera(surfaceTexture)
//        }

        if (surfaceTexture != null) {
            surfaceTexture?.updateTexImage()
            surfaceTexture?.getTransformMatrix(mtx)

        }


        checkGlError("glBindTextu222223222re23333232323232")
//        checkGlError("glBindTexturewewew")
        GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f)
        GLES20.glUseProgram(fboprogram)
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER,mFrameBuffers[0])
        checkGlError("glBindTexture23333232323232")

        checkGlError("glBindTexture2333323232323")

        checkGlError("glBindTexture23333232")
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
        checkGlError("glBindTexture2333")
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureOes[0])
//
        checkGlError("checkGlError22")
        checkGlError("glBindTexturewewew")
        GLES30.glUniformMatrix4fv(uTextureMatrix, 1, false, mtx, 0);
        checkGlError("glBindTexture23")
        GLES30.glBindVertexArray(vao[0])
        GLES30.glDrawElements(GLES30.GL_TRIANGLE_STRIP,6,GLES30.GL_UNSIGNED_INT,0)
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0)
        checkGlError("glBindTexture1")
        GLES30.glBindVertexArray(0)

       GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER,0)



//======================================================================================================================
        GLES20.glUseProgram(program)
        checkGlError("glBindTexture32")
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
        GLES20.glBindTexture(GLES30.GL_TEXTURE_2D, mFBOTextures[0])
        GLES30.glBindVertexArray(vao[0])
        checkGlError("glBindTexture23232323")
        GLES30.glDrawElements(GLES30.GL_TRIANGLE_STRIP,6,GLES30.GL_UNSIGNED_INT,0)
        //        id     fbo  的数据  int cpu   gpu
//        id      1       textures[0]   2
        surfaceTexture?.timestamp?.let { mMediaRecorder?.encodeFrame(mFBOTextures[0], it) }
        GLES20.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
        GLES30.glBindVertexArray(0)
        checkGlError("glBindTexture2323")






    }
}